package com.lsl.rdf.utils.encrypt;

import com.lsl.rdf.encrypt.EncryptOrDecryptException;
import org.apache.commons.lang.StringUtils;
import sun.misc.BASE64Decoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Objects;

/**
 * Created by lsl on 2021/6/1.
 */
public class AesUtil {

    //算法
    private static final String ALGORITHM_STR = "AES/ECB/PKCS5Padding";
    private static AesUtilContainer aesUtilContainer = new AesUtilContainer(128, ALGORITHM_STR);
    private static BASE64Decoder base64Decoder = new BASE64Decoder();

    /**
     * 字符串aes加密
     *
     * @param content 被加密内容
     * @param key     密钥
     * @return 加密串
     */
    public static String encrypt(String content, String key) {
        return encrypt(content, key, false);
    }

    /**
     * 字符串aes解密
     *
     * @param content 机密串
     * @param key     密钥
     * @return 解密串
     */
    public static String decrypt(String content, String key) {
        return decrypt(content, key, false);
    }

    public static String encrypt(String content, String key, boolean thrEx) {
        if (StringUtils.isBlank(content) || StringUtils.isBlank(key)) {
            return "";
        }
        byte[] bytes = null;
        try {
            Cipher cipher = aesUtilContainer.getCipher(Cipher.ENCRYPT_MODE, key);
            byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
            bytes = cipher.doFinal(contentBytes);
        } catch (Exception e) {
            e.printStackTrace();
            if (thrEx) {
                throw new EncryptOrDecryptException("AesUtil.encrypt 加密失败", e);
            }
        }
        if (Objects.isNull(bytes)) {
            return "";
        }
        return Base64.getEncoder().encodeToString(bytes);
    }


    public static String decrypt(String content, String key, boolean thrEx) {
        if (StringUtils.isBlank(content) || StringUtils.isBlank(key)) {
            return "";
        }
        byte[] bytes = null;
        try {
            Cipher cipher = aesUtilContainer.getCipher(Cipher.DECRYPT_MODE, key);
            byte[] decodeBuffer = base64Decoder.decodeBuffer(content);
            bytes = cipher.doFinal(decodeBuffer);
        } catch (Exception e) {
            e.printStackTrace();
            if (thrEx) {
                throw new EncryptOrDecryptException("AesUtil.decrypt 解密失败", e);
            }
        }
        if (Objects.isNull(bytes)) {
            return "";
        }
        return new String(bytes);
    }

    static class AesUtilContainer {
        private int init;
        private String algorithm;

        public AesUtilContainer(int init, String algorithm) {
            this.init = init;
            this.algorithm = algorithm;
        }

        public Cipher getCipher(int mode, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
            if (StringUtils.isBlank(key)) {
                throw new EncryptOrDecryptException("AesUtilContainer.getCipher 密钥不能为空");
            }

            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            KeyGenerator instance = KeyGenerator.getInstance("AES");

            instance.init(init);
            Cipher cipher = Cipher.getInstance(algorithm);
            cipher.init(mode, secretKeySpec);
            return cipher;
        }
    }
}
